/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package adc_lcard;

import dynamixel.ComPortFindParam;
import dynamixel.ComPortFinder;
import dynamixel.FindSerial;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.rowset.serial.SerialArray;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.Timer;
import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;
import jssc.SerialPortList;
import jssc.SerialPortTimeoutException;

/**
 *
 * @author Asko
 */
public class ADCE140Driver {

    final static int[] SEND_PACK = {0xaa, 0x01};
    final static int[] CHECK_PACK = {0xab, 0x01};
    final static int BYTES_CNT = 5;
    final static int BAUDRATE = 115200;
    final static int DATABITS = 8;
    final static int STOP_BITS = 1;
    final static int PARITY_NONE = 0;
    final static int TIMEOUT = 200;
    final static int SHIT_FILTER_VALUE = 50;
    final static int SHIT_MAX_CNT = 10;
    static SerialPort serialPort;
    static int inputBuf[];
    //static int resultBuf[] = new int[5];
    static int timeOut = 200;
    static int crc = 0;
    static boolean initADC = false;
    static int old_vals[] = new int[16];
    static int old_vals_cnt[] = new int[16];
    static boolean shitFiltering = true;
    /*native public static boolean init();

     native public static int getData(int channelNum);

     native public static int getGData(int channelNum);

     native public static int getDiffData(int channelNum);

     native public static boolean close();
     private static boolean isRunning = false;
 
     static {
     System.loadLibrary("libADCLibrary");
     }*/

    public static int getData(int channelNum) {
        return getGdata(channelNum);
    }

    public static boolean init() {
        boolean returnStatus = false;
        String comName = ComPortFinder.findCom(new ComPortFindParam(BAUDRATE,
                DATABITS, STOP_BITS, PARITY_NONE, BYTES_CNT, TIMEOUT) {
            @Override
            public boolean isFinded(int[] pckg) {
                return (getCRC(pckg) == pckg[4])
                        && pckg[0] == 0xab && pckg[1] == 1;
            }

            @Override
            public int[] getSendPckg() {
                return SEND_PACK;
            }
        });

        System.out.println("comName ADC: " + comName);
        if (comName != null) {
            try {
                serialPort = new SerialPort(comName);
                serialPort.openPort();

                returnStatus = serialPort.setParams(BAUDRATE, DATABITS, STOP_BITS, PARITY_NONE);
            } catch (SerialPortException ex) {
                Logger.getLogger(ADCE140Driver.class.getName()).log(Level.SEVERE, null, ex);
            }

        } else {
            System.out.println("ADC shit happened. Com name: " + comName);
            System.exit(1);
        }

        for (int i = 0; i < old_vals.length; i++) {
            old_vals[i] = -1;
            old_vals_cnt[i] = 0;
        }

        initADC = returnStatus;
        return returnStatus;
    }

    public static int getGdata(int channelNum) {
        if (!initADC) {
            return 0;
        }
        int sendBuf[] = {0xaa, channelNum - 1};
        int res = 0;
        try {
            serialPort.writeIntArray(sendBuf);
            int resultBuf[] = serialPort.readIntArray(BYTES_CNT, TIMEOUT);
            res = getCRC(resultBuf);
            if (res == resultBuf[4]) {
                res = (int) ((resultBuf[2] << 8 & 0xffff) | resultBuf[3]);
            } else {
                System.out.println("Error is CRC. CRC: " + res);
                System.out.println("resbuf: " + Arrays.toString(resultBuf));
                res = 0;
            }

        } catch (SerialPortTimeoutException ex) {
            //Logger.getLogger(ADCE140Driver.class.getName()).log(Level.SEVERE, null, ex);
            System.err.println("Error ADC timeout");
            return -1;
        } catch (SerialPortException ex) {
            //Logger.getLogger(ADCE140Driver.class.getName()).log(Level.SEVERE, null, ex);
            System.err.println("Error ADC SerialPt");
            return -1;

        }

        if (shitFiltering) {
            res = shitFilter(res, channelNum - 1);
        }

        return res;
    }

    public static int getDiffData(int channelNum) {
        return getGdata(channelNum);
    }

    private static int shitFilter(int val, int ch_num) {
        if (Math.abs(val - old_vals[ch_num]) < SHIT_FILTER_VALUE
                || old_vals_cnt[ch_num] > SHIT_MAX_CNT) {
            old_vals[ch_num] = val;
            old_vals_cnt[ch_num] = 0;
            return val;
        } else {
            old_vals_cnt[ch_num]++;

            return old_vals[ch_num];
        }
    }

    public static boolean close() {
        boolean closeStatus = false;
        if (serialPort.isOpened()) {
            try {
                serialPort.closePort();
                closeStatus = true;
            } catch (SerialPortException ex) {
                Logger.getLogger(ADCE140Driver.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
        return closeStatus;
    }

    public static boolean isInitADC() {
        return initADC;
    }

    public static int getCRC(int resultBuf[]) {
        return resultBuf.length > 3 ? 0xff - ((resultBuf[1] + resultBuf[2] + resultBuf[3]) & 0xff) : -1;
    }

    public static void main(String[] args) throws InterruptedException {
//        if (!ADCE140Driver.init()) {
//            System.out.println("Shit happened");
//            System.exit(1);
//        }
////        int ch = 2;
////        int res = 9;
////        for (int i = 0; i < 1000; i++) {
////            // for (int k = 0; k < 16; k++) {
////            res = (int) (ADCE140Driver.getGdata(ch));
////            System.out.println("Ch num : " + ch + " Data: "
////                    + res);
////            Thread.sleep(5);
////            //    }
////
////            Thread.sleep(10);
////        }
//        ADCE140Driver.close();
    }

    public static void setShitFiltering(boolean shitFiltering) {
        ADCE140Driver.shitFiltering = shitFiltering;
    }
}
